+function ($) {
  'use strict';

  // CITYSELECTOR CLASS DEFINITION
  // ==========================

  var CitySelector = function (element, options) {
    var filters; /* data-filter-codes value in array */

    this.$element = $(element);
    this.options  = options;
    this.filters = String(this.$element.data('filterCodes'));
    this.filters = this.filters !== 'undefined' ? this.filters.split(',') : false;

    this.$element.on('provChanged.jq.cityselector', $.proxy(this.provChanged, this));
    this.$element.on('cityChanged.jq.cityselector', $.proxy(this.cityChanged, this));
    this.$selects = this.$element.find('select');
    this.$selects.on('change', function(event) {
      var $el = $(event.target);
      var cityselector = $el.closest('[data-toggle=cityselector]').data('jq.cityselector');
      var role = $el.data('role');
      if (role === 'province') cityselector.$element.trigger('provChanged.jq.cityselector', $el);
      else if (role === 'city') cityselector.$element.trigger('cityChanged.jq.cityselector', $el);
    });

    // find provinces and init the first select input.
    this.init();
  };

  CitySelector.DEFAULTS = {
    defaultOption: ''
  };

  CitySelector.prototype.init = function() {
    var $provSelect = this.getProvinceSelect();

    $provSelect.empty().append('<option value="' + this.options.defaultOption + '">请选择</option>');

    var self = this;
    var provinces = this.getProvinces();
    $.each(provinces,function(index, prov) {
      if (self.filters && self.filters.indexOf(prov.code) === -1) return;
      var $opt = $('<option></option>');
      $opt
        .val(prov.code)
        .text(prov.name)
        .appendTo($provSelect);
    });

   /* this.getProvinces().forEach(function(prov, index) {
      if (self.filters && self.filters.indexOf(prov.code) === -1) return;
      var $opt = $('<option></option>');
      $opt
        .val(prov.code)
        .text(prov.name)
        .appendTo($provSelect);
    });*/

    var userOption = $provSelect.data('selected');
    if (userOption) {
      $provSelect.find('option[value='+userOption+']').attr('selected', 'selected');
      $provSelect.trigger('provChanged.jq.cityselector');
    }
  };

  CitySelector.prototype.getProvinces = function() {
    return common_assets.cities.getAllProvinces();
  };

  CitySelector.prototype.getCities = function (isAreaAsCity) {
    var isAreaAsCity = isAreaAsCity || false;
    var provCode = this.getProvinceSelect().val();
    return common_assets.cities.getCitiesByCode(provCode, isAreaAsCity);
  };

  CitySelector.prototype.getAreas = function () {
    var cityCode = this.getCitySelect().val();
    var cities = this.getCities();
    for (var index in cities) {
      var city = cities[index];
      if (city.code === cityCode) return city.area;
    }
    return null;
  };

  CitySelector.prototype.getProvinceSelect = function() {
    return this.$element.find('[data-role=province]');
  };

  CitySelector.prototype.getCitySelect = function() {
    return this.$element.find('[data-role=city]');
  };

  CitySelector.prototype.getAreaSelect = function() {
    return this.$element.find('[data-role=area]');
  };

  CitySelector.prototype.provChanged = function(event) {
    var $provSelect = this.getProvinceSelect();
    var $citySelect = this.getCitySelect();
    var $areaSelect = this.getAreaSelect();

    // 当没有 area <select> 的时候，便是需要把直辖市的区上升为市的时候。
    var cities = this.getCities($areaSelect.length === 0);

    $citySelect.empty().append('<option value="' + this.options.defaultOption + '">请选择</option>');
    $areaSelect.empty();

    // 如果［省］选择了 ---, 处理这种情况.
    if ($provSelect.val() == "0") return;

    var self = this;

    $.each(cities,function(index, city) {
      if (self.filters && self.filters.indexOf(city.code) === -1) return;
      var $opt = $('<option></option>');
      $opt
        .val(city.code)
        .text(city.name)
        .appendTo($citySelect);
    });

    /*cities.forEach(function(city, index) {
      if (self.filters && self.filters.indexOf(city.code) === -1) return;
      var $opt = $('<option></option>');
      $opt
        .val(city.code)
        .text(city.name)
        .appendTo($citySelect);
    });*/

    var userOption = $citySelect.data('selected');
    if (userOption) {
      $citySelect.find('option[value='+userOption+']').attr('selected', 'selected');
      $citySelect.trigger('cityChanged.jq.cityselector');
    } else {
      $citySelect.find('option:first').attr('selected', true);
    }
  };

  CitySelector.prototype.cityChanged = function(event) {
    var $citySelect = this.getCitySelect();
    var $areaSelect = this.getAreaSelect();
    if ($areaSelect.length === 0) return;
    var areas = this.getAreas();

    $areaSelect.empty().append('<option value="' + this.options.defaultOption + '">请选择</option>');

    // 如果［市］选择了 ---, 处理这种情况.
    if ($citySelect.val() == "0") return;

    var self = this;
    $.each(areas,function(index, area) {
      if (self.filters && self.filters.indexOf(area.code) === -1) return;
      var $opt = $('<option></option>');
      $opt
        .val(area.code)
        .text(area.name)
        .appendTo($areaSelect);
    });

    /*areas.forEach(function(area, index) {
      if (self.filters && self.filters.indexOf(area.code) === -1) return;
      var $opt = $('<option></option>');
      $opt
        .val(area.code)
        .text(area.name)
        .appendTo($areaSelect);
    });*/

    var userOption = $areaSelect.data('selected');
    if (userOption) {
      $areaSelect.find('option[value='+userOption+']').attr('selected', 'selected');
    } else {
      $areaSelect.find('option:first').attr('selected', true);
    }
  };

  CitySelector.prototype.select = function(event) {
    var role = $(this).data('role');
  };

  // CITYSELECTOR PLUGIN DEFINITION
  // ===========================


  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var options = $.extend({}, CitySelector.DEFAULTS, $this.data(), typeof option == 'object' && option)
      var data    = $this.data('jq.cityselector')

      if (!data && option == 'destroy') return
      if (!data) $this.data('jq.cityselector', (data = new CitySelector(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.cityselector

  $.fn.cityselector             = Plugin
  $.fn.cityselector.Constructor = CitySelector


  // CITYSELECTOR NO CONFLICT
  // =====================

  $.fn.cityselector.noConflict = function () {
    $.fn.cityselector = old
    return this
  }


  // CITYSELECTOR DATA-API
  // ==================

  $(window).on('load', function () {
    $('[data-toggle="cityselector"]').each(function () {
      var $el = $(this);
      Plugin.call($el, $el.data());
    })
  })

}(jQuery);
